npm-scripts でチームメンバーと共通認識を作る
npm-scripts とは package.json の scripts
プロパティで定義する、一連の便利処理です。本記事では、 npm-scripts を使った開発効率の加速と、プロジェクトにジョインしたらまず npm-scripts を把握すべき理由、最後に npm-scripts を補完する方法を紹介します。
この記事は CX 事業本部の Tech Lead のお仕事紹介第 5 弾です。
TL;DR
test
スクリプトは必ず定義しようstart
スクリプトは定義できる場合は必ず定義しよう- スクリプトにはわかりやすい名前をつけよう
- プロジェクトでの作業はできるだけスクリプトを使おう
- ソースコードはスクリプトから追っていこう
- 楽するためにスクリプト名補完の設定をしよう
npm-scripts とは ?
npm run-script <スクリプト名>
と打つことで、 <スクリプト名>
に指定したスクリプトを実行可能な npm の仕組みです。 run-script
サブコマンドは少々長いので、 run
エイリアスが用意されています。これによって npm run <スクリプト名>
と打つことが可能になります。実際の使用は run
サブコマンドを使うことが普通です。
<スクリプト名>
にあたる部分は package.json の scripts
プロパティで定義します。
{ "scripts": { "myFirstScript": "echo done" }, }
これは myFirstScript
というスクリプトを定義している例です。 npm run myFirstScript
を実行可能となり、実行結果として done
という文字列が表示されます。
$ npm run myFirstScript > [email protected] myFirstScript /path/to/your/project > echo done done
特別扱いのスクリプト名
次の名前を持つスクリプトは特別扱いです。
- test
- start
これらは run
サブコマンドを指定する必要がなく、それぞれ npm test
および npm start
で実行可能です。また、 test
は t
および tst
というエイリアスを持っているため、 npm t
もしくは npm tst
で実行可能です。
test
はテストを実行する意味合いをもっているスクリプト名です。使い捨てのプロジェクトを除き、必ず定義しましょう。プロジェクトへのジョイン時や久しぶりにコードを触る際にまずテスト実行し、プロジェクト把握や変更の足がかりとすると良いでしょう。
start
はそのプロジェクトで提供すべきものを実行するためのスクリプト名です。たとえばサーバー用のプロジェクトであればサーバーを立ち上げるための定義を、コマンドラインを提供するプロジェクトであればそのコマンドラインを実行するための定義を書きましょう。フロントエンド開発プロジェクトではバンドル用のサーバーを立ち上げるなどの用途で利用されます。関数のみを提供するなど、ライブラリーとして提供される目的のプロジェクトでは定義しなくとも構いません。
pre
と post
スクリプト名の前に pre
をつけたものは該当スクリプトの実行直前に実行されます。また、該当スクリプトの実行直後に実行される post
プリフィクスも存在しています。 test
、 pretest
、 posttest
が定義されている際に test
を実行すると次の順番で実行されます。
pretest
test
posttest
それぞれ前準備と後処理を定義したい場合に使いましょう。
なお、 preinstall
や postinstall
を定義すると、パッケージがインストールされる直前と直後に実行する処理を指定可能です。セキュリティを確保する目的で使用が推奨されていませんが、プロジェクトメンバーのみの参照に限定されているプロジェクトで、使用者の手元でビルドが必要なパッケージを作成する際などに使用しましょう。
同様に prepublish
という publish
前に実行する処理も定義可能ですが、歴史的経緯によって使用を一時的に控える必要があります。現在、 prepublish
相当のことを定義したい場合は代わりに prepublishOnly
を定義しましょう。遠くない未来に prepublishOnly
が deprecated になったという警告メッセージが表示されるようになりますので、その際に prepublishOnly
を prepublish
へ変更しましょう。
その他あると便利なスクリプト
次のスクリプトを定義しておくと便利でしょう。
スクリプト名 | 目的 |
---|---|
build | ビルド |
clean | ビルド結果の削除 |
type-check | 型チェック |
lint | 静的コード解析 |
coverage | コードカバレッジ計測 |
型チェックや静的コード解析については、普段エディターや IDE で自動的に実行していると思いますが、 CI 用に定義しておくと便利です。また、これらが明示的に定義してあることでジョインしたばかりのプロジェクトメンバーがそれぞれの目的でどのツールを使うかを把握することが可能です。
スクリプト名の修飾
例えば development
環境と production
環境でビルド用の設定が異なる場合など、実行すべきスクリプトを変更したいときがあります。これは慣習的に :
コロンでつないで環境名を指定することが多いです。例えば普段使う build
コマンドは development
環境用とし、 build:prod
コマンドに production
環境用のスクリプトを定義する、などです。
yarn における scripts プロパティの扱い
yarn も同様の仕組みを持っており、 yarn run <スクリプト名>
と打つことで実行可能です。
ただし、 yarn では run
サブコマンドを省略可能です。次のコマンド群はまったく同じ動作となります。
yarn run myFirstScript
yarn myFirstScript
また、 test
スクリプトのエイリアスは特に設定されていません。そのため yarn t
は実行できず、 yarn test
と打つ必要があります。
$ yarn myFirstScript yarn run v1.22.4 $ echo done done ✨ Done in 0.04s.
yarn でスクリプトを実行した場合、最後に実行時間が表示されます。
package.json 例
ここで一度 package.json の例を挙げてみます。scripts
プロパティ以外は省略しています。
{ "scripts": { "start": "webpack-dev-server --config webpack.config.wds.js", "build": "webpack --config webpack.config.dev.js", "build:prod": "webpack --config webpack.config.prod.js", "type-check": "tsc --noEmit", "lint": "eslint --ext '.ts' --ext '.tsx' .", "test": "jest", "coverage": "jest --coverage", } }
webpack を用いたフロントエンドプロジェクトの例です。 start
、test
の他、環境別の build
やその他チェック用のスクリプトを定義しています。
CI 設定で type-check
/ lint
/ coverage
などを用いるとよいですね。
スクリプトからプロジェクトの構造を追う
さて、上述した package.json を持つプロジェクトにジョインした方がどのようにプロジェクトを把握するかを追ってみましょう。
まず依存パッケージの挙動が変わることによって壊れていないかを確かめようとするでしょう。その際は scripts
プロパティを眺め、 test
スクリプトが定義されていることを発見し、実行するでしょう。 Node.js プロジェクトに慣れている方であればスクリプトの定義を確認せずに npm t
や yarn test
をまず実行するかもしれません。
ここで、 test
には Jest を使っていることがわかるため、 jest.config.js や package.json の jest
プロパティを参照してテストに関する設定を確認することが可能です。また、各テストケースを確認するためには __tests__
ディレクトリーや .test.ts
拡張子がついたファイルを探せばよいこともわかりますね。
同様にプロジェクトを動かしたいと思った際も start
スクリプトを探して実行するという流れとなります。もし start
スクリプトが定義されていない場合、そのプロジェクトでは何も実行するものがない、と解釈されるでしょう。
上述の例では、 start
スクリプトは webpack-dev-server を用いてフロントエンド開発用のサーバーを立ち上げる定義となっています。こちらは指定されている設定ファイルを参照し、エントリーポイントからコードをたどっていくことが可能です。
複数行のスクリプトを使いたい場合
少し複雑な処理など、 1 行での定義が難しい場合は別途シェルスクリプトや JavaScript で処理を書き下すなどし、それを各種 npm-scripts に指定しましょう。
bin
ディレクトリーは実行可能なパッケージを作成する際に使うものという慣習があるため、 utils
や scripts
ディレクトリーなどに格納しましょう。
/ scripts/ awesome.sh package.json
上述のようなファイルツリーの構造とし、 package.json の中身は次としましょう。
{ "scripts": { "awesome": "./scripts/awesome.sh" } }
スクリプト名の補完
デフォルトではスクリプト名は補完対象になっていません。これではいちいち package.json の中身を覗いて使用可能なものを確認する必要があるだけでなく、スクリプト名をすべて打たなければならないので面倒くさいです。これを補完可能とする設定を紹介します。
npm では npm completion
サブコマンドの実行結果をお使いのシェルの設定ファイルに書き込むことで補完が効くようになります。スクリプトだけでなくサブコマンドの補完も効くようになるため、ぜひ設定しましょう。
ただし、この設定は補完時に npm completion
サブコマンドを呼び出しているせいか一瞬の待ちが発生します。この待ちが嫌な方は自分で補完用の設定を書いてみましょう。手元では jq コマンドで package.json をパースすることで素早く補完されるようになりました。なお、この設定例は zsh 用です。 bash など他のシェルをお使いの方は参考にして自分で書いてみてください。
他にも peco を使って補完する方法で快適な環境を作成している方もいらっしゃいます。 bash での設定例なので普段遣いされている方にはとても参考になる記事です。
yarn ではすでに有志の方による zsh 用補完関数が提供されていたのでこちらを利用しました。 bash その他のシェルの情報をお持ちの方は教えて下さい。
まとめ
npm-scripts の定義方法から実際の使い方までを紹介しました。普段プロジェクトをメンテナンスされている方は意識して各スクリプトを整備してみましょう。また、今後新しいプロジェクトにジョインする際は本記事で紹介した方法を使ってプロジェクト構造を把握することに挑戦してみてください。
なお、 npm-scripts ですべての齟齬が解消されるわけではありません。適宜 README に補足事項を書いたり、話し合って積極的に共通認識の形成を図りましょう。本記事はそのための足がかりとして使っていただければ本望です。